package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.UserWalletListDto;
import com.frejoys.common.dto.app.UserWalletLogPageDto;
import com.frejoys.common.dto.common.IdDto;
import com.frejoys.common.enums.EUserWalletLogType;
import com.frejoys.common.util.AppConfigUtil;
import com.frejoys.common.util.CommonUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.admin.UserWalletListVo;
import com.frejoys.common.vo.app.*;
import com.frejoys.dao.entity.User;
import com.frejoys.dao.entity.UserWallet;
import com.frejoys.dao.entity.UserWalletLog;
import com.frejoys.dao.mapper.UserMapper;
import com.frejoys.dao.mapper.UserWalletLogMapper;
import com.frejoys.dao.mapper.UserWalletMapper;
import com.frejoys.service.UserService;
import com.frejoys.service.UserWalletService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServer;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserWalletServiceImpl extends ServiceImpl<UserWalletMapper, UserWallet> implements UserWalletService {

    private final UserService userService;

    private final UserWalletLogMapper userWalletLogMapper;

    private final UserMapper userMapper;

//    @Override
//    public UserWalletVo userWalletInfo(Long userId) {
//        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper();
//        wrapper.eq(UserWallet::getUserId,userId);
//
//        UserWallet userWallet = getOnly(wrapper);
//        User user = userService.getInfo(userId);
//
//        UserWalletVo vo = new UserWalletVo();
//        vo.setNickname(user.getNickname());
//        vo.setAvatar(AppConfigUtil.getUrlPrefix(user.getAvatar()));
//
//        if (userWallet == null){
//            return vo;
//        }
//
//        vo.setId(userWallet.getId());
//        vo.setScore(userWallet.getScore());
//        vo.setSpendMoney(userWallet.getSpendMoney());
//        vo.setMoney(userWallet.getMoney());
//        return vo;
//    }


    @Override
    public UserWalletInfoVo userWalletDetails(Long userId) {
        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWallet::getUserId,userId);
        UserWallet userWallet = getOnly(wrapper);
        UserWalletInfoVo vo = BeanUtil.copyProperties(userWallet, UserWalletInfoVo.class);

        //当日起始时间
        int startTime = TimeUtil.beginOfDay(TimeUtil.unixTime());

        //当日结束时间
        int endTime = TimeUtil.endOfDay(TimeUtil.unixTime());

        LambdaQueryWrapper<UserWalletLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserWalletLog::getUserId,userId)
                .ge(UserWalletLog::getCreateTime,startTime)
                .le(UserWalletLog::getCreateTime,endTime);
        List<UserWalletLog> userWalletLogs = userWalletLogMapper.selectList(queryWrapper);

        //今日返利金额
        BigDecimal rebateMoneyDay = BigDecimal.ZERO;
        //今日代理佣金
        BigDecimal agentMoneyDay = BigDecimal.ZERO;
        //今日达人佣金
        BigDecimal activeMoneyDay = BigDecimal.ZERO;

        if (!userWalletLogs.isEmpty()){
            for (UserWalletLog userWalletLog:userWalletLogs){
                if (userWalletLog.getType() == EUserWalletLogType.orderRebate.getValue()){
                    rebateMoneyDay = CommonUtil.bigDecimalAdd(rebateMoneyDay,userWalletLog.getMoney());
                }
                if (userWalletLog.getType() == EUserWalletLogType.promotionRebate.getValue() || userWalletLog.getType() == EUserWalletLogType.promotionRecommendRebate.getValue()){
                    activeMoneyDay = CommonUtil.bigDecimalAdd(activeMoneyDay,userWalletLog.getMoney());
                }
                if (userWalletLog.getType() == EUserWalletLogType.agentRebate.getValue() || userWalletLog.getType() == EUserWalletLogType.agentRecommendRebate.getValue() || userWalletLog.getType() == EUserWalletLogType.agentCashRebate.getValue() || userWalletLog.getType() == EUserWalletLogType.groupRebate.getValue()){
                    agentMoneyDay = CommonUtil.bigDecimalAdd(agentMoneyDay,userWalletLog.getMoney());
                }
            }
        }
        vo.setAgentMoneyDay(agentMoneyDay);
        vo.setRebateMoneyDay(rebateMoneyDay);
        vo.setActiveMoneyDay(activeMoneyDay);
//        vo.setSumMoney(vo.getActiveMoneyTotal().add(vo.getRebateMoneyTotal()).add(vo.getAgentMoneyTotal()));
        vo.setSumMoney(CommonUtil.bigDecimalAdd(vo.getMoney(), vo.getRebateMoney(), vo.getAgentMoney(), vo.getActiveMoney()));
        return vo;
    }


    @Override
    public UserWalletMoneyVo userWalletMoney(Long userId) {

        UserWalletMoneyVo vo = new UserWalletMoneyVo();

        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserWallet::getMoney,UserWallet::getId).eq(UserWallet::getUserId,userId);
        UserWallet userWallet = getOnly(wrapper);

        //取出余额列表第一条数据时间
        LambdaQueryWrapper<UserWalletLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserWalletLog::getCreateTime)
                .eq(UserWalletLog::getUserId,userId)
                .ge(UserWalletLog::getType,EUserWalletLogType.toRebate.getValue())
                .le(UserWalletLog::getType,EUserWalletLogType.toAgent.getValue())
                .or().eq(UserWalletLog::getUserId,userId)
                .eq(UserWalletLog::getType,EUserWalletLogType.cash.getValue())
                .orderByAsc(UserWalletLog::getCreateTime)
                .last("LIMIT 1");
        UserWalletLog userWalletLog = userWalletLogMapper.selectOne(queryWrapper);

        if (!ObjectUtil.isEmpty(userWallet)){
            vo.setId(userWallet.getId());
            vo.setMoney(userWallet.getMoney());
        }
        if (!ObjectUtil.isEmpty(userWalletLog)){
            vo.setTime(userWalletLog.getCreateTime());
        }else {
            vo.setTime(TimeUtil.unixTime());
        }
        return vo;
    }


    @Override
    public FreeOrderDetailsVo freeOrderDetails(Long userId) {

        FreeOrderDetailsVo vo = new FreeOrderDetailsVo();

        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserWallet::getId,UserWallet::getRebateMoney,UserWallet::getRebateMoneyTotal)
                .eq(UserWallet::getUserId,userId);
        UserWallet userWallet = getOnly(wrapper);

        List<Integer> types = new ArrayList<>();
        types.add(EUserWalletLogType.orderRebate.getValue());
        //查询订单当日返利
        BigDecimal dayMoney = getDayMoney(userId,types);

        Integer time = getOneTime(userId, EUserWalletLogType.orderRebate.getValue(), EUserWalletLogType.outRebate.getValue());

        if (!ObjectUtil.isEmpty(userWallet)){
            vo.setId(userWallet.getId());
            vo.setRebateMoney(userWallet.getRebateMoney());
            vo.setRebateMoneyTotal(userWallet.getRebateMoneyTotal());
        }
        vo.setRebateMoneyDay(dayMoney);
        vo.setTime(time);
        return vo;
    }


    @Override
    public PromotionBrokerageDetailsVo promotionBrokerageDetails(Long userId) {
        PromotionBrokerageDetailsVo vo = new PromotionBrokerageDetailsVo();

        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserWallet::getId,UserWallet::getActiveMoney,UserWallet::getActiveMoneyTotal)
                .eq(UserWallet::getUserId,userId);
        UserWallet userWallet = getOnly(wrapper);

        List<Integer> types = new ArrayList<>();
        types.add(EUserWalletLogType.promotionRebate.getValue());
        types.add(EUserWalletLogType.promotionRecommendRebate.getValue());
        //查询达人当日返利金额
        BigDecimal dayMoney = getDayMoney(userId,types);

        Integer time = getOneTime(userId, EUserWalletLogType.promotionRebate.getValue(),EUserWalletLogType.outPromotion.getValue());

        if (!ObjectUtil.isEmpty(userWallet)){
            vo.setId(userWallet.getId());
            vo.setActiveMoney(userWallet.getActiveMoney());
            vo.setActiveMoneyTotal(userWallet.getActiveMoneyTotal());
        }
        vo.setActiveMoneyDay(dayMoney);
        vo.setTime(time);
        return vo;
    }


    @Override
    public AgentBrokerageDetailsVo agentBrokerageDetails(Long userId) {
        AgentBrokerageDetailsVo vo = new AgentBrokerageDetailsVo();

        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserWallet::getId,UserWallet::getAgentMoney,UserWallet::getAgentMoneyTotal)
                .eq(UserWallet::getUserId,userId);
        UserWallet userWallet = getOnly(wrapper);

        List<Integer> types = new ArrayList<>();
        types.add(EUserWalletLogType.agentRebate.getValue());
        types.add(EUserWalletLogType.agentRecommendRebate.getValue());
        types.add(EUserWalletLogType.agentCashRebate.getValue());
        types.add(EUserWalletLogType.groupRebate.getValue());
        //查询代理当日返利金额
        BigDecimal dayMoney = getDayMoney(userId,types);

        Integer time = getOneTime(userId, EUserWalletLogType.agentRebate.getValue(),EUserWalletLogType.groupRebate.getValue());

        if (!ObjectUtil.isEmpty(userWallet)){
            vo.setId(userWallet.getId());
            vo.setAgentMoney(userWallet.getAgentMoney());
            vo.setAgentMoneyTotal(userWallet.getAgentMoneyTotal());
        }
        vo.setAgentMoneyDay(dayMoney);
        vo.setTime(time);
        return vo;
    }


    @Override
    public IPage<UserWalletListVo> walletList(UserWalletListDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());

        LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
        if (dto.getUserId() != null){
            wrapper.eq(UserWallet::getUserId,dto.getUserId());
        }
        if (StrUtil.isNotEmpty(dto.getNickname())){
            List<Long> userIds = userMapper.nicknameByUserId(dto.getNickname());
            if (userIds.isEmpty()){
                return new Page<>();
            }
            wrapper.in(UserWallet::getUserId,userIds);
        }
        if (StrUtil.isNotEmpty(dto.getPhone())){
            Long userId = userMapper.phoneByUserId(dto.getPhone());
            if (userId == null){
                return new Page<>();
            }
            wrapper.eq(UserWallet::getUserId,userId);
        }

        Page<UserWallet> userWalletPage = baseMapper.selectPage(page, wrapper);
        IPage<UserWalletListVo> walletPage = userWalletPage.convert(userWallet -> BeanUtil.copyProperties(userWallet, UserWalletListVo.class));
        List<UserWalletListVo> walletList = walletPage.getRecords();

        if (!walletList.isEmpty()){
            List<Long> userIds = walletList.stream().map(UserWalletListVo::getUserId).toList();

            //查询用户信息
            List<User> users = userMapper.getUserByIds(userIds);
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

            for (UserWalletListVo vo:walletList) {

                if (userMap.containsKey(vo.getUserId())){
                    User user = userMap.get(vo.getUserId());
                    vo.setNickname(user.getNickname());
                    vo.setPhone(user.getPhone());
                    vo.setAvatarUrl(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                }
            }
        }
        return walletPage;
    }


    //查询第一条记录时间
    private Integer getOneTime(Long userId, Integer startType, Integer endType) {
        Integer time = 0;

        LambdaQueryWrapper<UserWalletLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserWalletLog::getCreateTime)
                .eq(UserWalletLog::getUserId,userId)
                .ge(UserWalletLog::getType,startType)
                .le(UserWalletLog::getType,endType)
                .orderByAsc(UserWalletLog::getCreateTime)
                .last("LIMIT 1");
        UserWalletLog userWalletLog = userWalletLogMapper.selectOne(queryWrapper);
        if (!ObjectUtil.isEmpty(userWalletLog)){
            time = userWalletLog.getCreateTime();
        }else {
            time = TimeUtil.unixTime();
        }
        return time;
    }


    //查询当日金额
    private BigDecimal getDayMoney(Long userId,List<Integer> types) {

        //当日起始时间
        int startTime = TimeUtil.beginOfDay(TimeUtil.unixTime());

        //当日结束时间
        int endTime = TimeUtil.endOfDay(TimeUtil.unixTime());

        LambdaQueryWrapper<UserWalletLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserWalletLog::getMoney)
                .eq(UserWalletLog::getUserId,userId)
                .ge(UserWalletLog::getCreateTime,startTime)
                .le(UserWalletLog::getCreateTime,endTime)
                .in(UserWalletLog::getType,types);
        List<UserWalletLog> userWalletLogs = userWalletLogMapper.selectList(queryWrapper);
        //今日返利金额
        BigDecimal dayMoney = BigDecimal.ZERO;

        if (!userWalletLogs.isEmpty()) {
            for (UserWalletLog userWalletLog : userWalletLogs) {
                dayMoney = CommonUtil.bigDecimalAdd(dayMoney,userWalletLog.getMoney());
            }
        }
        return dayMoney;
    }
}
